#include "GVoxel.h"
#include <stdlib.h>

void gvcleanStateData( _GVOXEL_STATE_DATA& StateData )
{
	StateData.nExtendedDataSize = 0;
	if( StateData.pExtendedData )
	{
		free( StateData.pExtendedData );
		StateData.pExtendedData = 0;
	}
};

void gvcleanVoxelLayerData( _GVOXEL_LAYER_DATA& LayerData )
{
	if( LayerData.lstStateData ) 
	{
		uint32_t count = GVOXEL_LAYER_WIDTH*GVOXEL_LAYER_DEPTH;
		for( uint32_t i=0; i<count; i++ )
			gvfreeStateData( &LayerData.lstStateData[i] );
		free( LayerData.lstStateData );
		LayerData.lstStateData = 0;
	}
	LayerData.nExtendedDataSize = 0;
	if( LayerData.pExtendedData )
	{
		free( LayerData.pExtendedData );
		LayerData.pExtendedData = 0;
	}
};

void gvcleanVoxelChunkData( _GVOXEL_CHUNK_DATA& ChunkData )
{
	if( ChunkData.lstLayerData ) 
	{
		uint32_t count = GVOXEL_LAYER_COUNT;
		for( uint32_t i=0; i<count; i++ )
			gvfreeLayerData( &ChunkData.lstLayerData[i] );
		free( ChunkData.lstLayerData );
		ChunkData.lstLayerData = 0;
	}
	ChunkData.nExtendedDataSize = 0;
	if( ChunkData.pExtendedData )
	{
		free( ChunkData.pExtendedData );
		ChunkData.pExtendedData = 0;
	}
};

void gvcleanRegionData( _GVOXEL_REGION_DATA& RegionData )
{
	uint32_t count = GVOXEL_REGION_WIDTH*GVOXEL_REGION_HEIGHT*GVOXEL_REGION_DEPTH;
	if( RegionData.lstChunkData )
	{
		for( uint32_t i=0; i<count; i++ )
			gvfreeChunkData( &RegionData.lstChunkData[i] );
		free( RegionData.lstChunkData );
		RegionData.lstChunkData = 0;
	}
	RegionData.nExtendedDataSize = 0;
	if( RegionData.pExtendedData )
	{
		free( RegionData.pExtendedData );
		RegionData.pExtendedData = 0;
	}
};


// gvCreateStateData
// NOTES: this function crashes with NULL input
void gvcreateStateData( _GVOXEL_STATE_DATA** ppCreated )
{
	(*ppCreated) = (_GVOXEL_STATE_DATA*)malloc( sizeof(_GVOXEL_STATE_DATA) );
	if( 0 == (*ppCreated) )
	{
		printf("malloc() FAILED! Out of memory?\n");
		return;// return -1;
	}
	(*ppCreated)->nRefCount			= 1; // init the counter
	// we should better initialize this data from parameters instead of empty values
	(*ppCreated)->pExtendedData		= 0; // same with sizes
	(*ppCreated)->nExtendedDataSize	= 0;
//	return 0;
};

void gvacquireStateData( _GVOXEL_STATE_DATA* pStateData )
{
	if( 0 != pStateData )
	{
//#ifdef WIN32
//		InterlockedIncrement( &pStateData->nRefCount ); // Still don't know if this works as I expect (perform atomic increase for thread-safety concerns)
//#else
		pStateData->nRefCount++;
//#endif
	}
}

// gvFreeStateData
// this function crashes with NULL input
void gvfreeStateData( _GVOXEL_STATE_DATA** ppStateData )
{
	if( 0 != (*ppStateData) )
	{
//#ifdef WIN32
//		if( 0 == InterlockedDecrement( &(*ppStateData)->nRefCount ) ) 
//#else
		if( 0 == --((*ppStateData)->nRefCount) )
//#endif
		{
			gvcleanVoxelStateData( **ppStateData );
			free( (*ppStateData) );
		}
		(*ppStateData)	= 0;
	}
};

// gvCreateLayerData
// NOTES: this function crashes with NULL input
void gvcreateLayerData( _GVOXEL_LAYER_DATA** ppCreated )
{
	(*ppCreated) = (_GVOXEL_LAYER_DATA*)malloc( sizeof(_GVOXEL_LAYER_DATA) );
	if( 0 == (*ppCreated) )
	{
		printf("malloc() FAILED! Out of memory?\n");
		return;// return -1;
	}
	(*ppCreated)->nRefCount			= 1; // init the counter
	// we should better initialize this data from parameters instead of empty values
	(*ppCreated)->lstStateData		= 0; // right now, pointers must be assigned after calling this function
	(*ppCreated)->pExtendedData		= 0; // same with sizes
	(*ppCreated)->nExtendedDataSize	= 0;
	//return 0;
};

void gvacquireLayerData( _GVOXEL_LAYER_DATA* pLayerData )
{
	if( 0 != pLayerData )
	{
//#ifdef WIN32
//		InterlockedIncrement( &pLayerData->nRefCount ); // Still don't know if this works as I expect (perform atomic increase for thread-safety concerns)
//#else
		pLayerData->nRefCount++;
//#endif
	}
}

// gvFreeLayerData
// this function crashes with NULL input
void gvfreeLayerData( _GVOXEL_LAYER_DATA** ppLayerData )
{
	if( 0 != (*ppLayerData) )
	{
//#ifdef WIN32
//		if( 0 == InterlockedDecrement( &(*ppLayerData)->nRefCount ) ) 
//#else
		if( 0 == --((*ppLayerData)->nRefCount) )
//#endif
		{
			gvcleanVoxelLayerData( **ppLayerData );
			free( (*ppLayerData) );
		}
		(*ppLayerData)	= 0;
	}
};



// gvCreateChunkData
// NOTES: this function crashes with NULL input
void gvcreateChunkData( _GVOXEL_CHUNK_DATA** ppCreated )
{
	(*ppCreated) = (_GVOXEL_CHUNK_DATA*)malloc( sizeof(_GVOXEL_CHUNK_DATA) );
	if( 0 == (*ppCreated) )
	{
		printf("malloc() FAILED! Out of memory?\n");
		return;// return -1;
	}
	(*ppCreated)->nRefCount			= 1; // init the counter
	// we should better initialize this data from parameters instead of empty values
	(*ppCreated)->lstLayerData		= 0; // right now, pointers must be assigned after calling this function
	(*ppCreated)->pExtendedData		= 0; // same with sizes
	(*ppCreated)->nExtendedDataSize	= 0;
};

void gvacquireChunkData( _GVOXEL_CHUNK_DATA* pChunkData )
{
	if( 0 != pChunkData )
	{
//#ifdef WIN32
//		InterlockedIncrement( &pChunkData->nRefCount ); // Still don't know if this works as I expect (perform atomic increase for thread-safety concerns)
//#else
		pChunkData->nRefCount++;
//#endif
	}
}

// gvFreeChunkData
// this function crashes with NULL input
void gvfreeChunkData( _GVOXEL_CHUNK_DATA** ppChunkData )
{
	if( 0 != (*ppChunkData) )
	{
//#ifdef WIN32
//		if( 0 == InterlockedDecrement( &(*ppChunkData)->nRefCount ) ) 
//#else
		if( 0 == --((*ppChunkData)->nRefCount) )
//#endif
		{
			gvcleanVoxelChunkData( **ppChunkData );
			free( (*ppChunkData) );
		}
		(*ppChunkData)	= 0;
	}
};



// gvCreateRegionData
// NOTES: this function crashes with NULL input
void gvcreateRegionData( _GVOXEL_REGION_DATA** ppCreated )
{
	(*ppCreated) = (_GVOXEL_REGION_DATA*)malloc( sizeof(_GVOXEL_REGION_DATA) );
	if( 0 == (*ppCreated) )
	{
		printf("malloc() FAILED! Out of memory?\n");
		return;// return -1;
	}
	(*ppCreated)->nRefCount			= 1; // init the counter
	// we should better initialize this data from parameters instead of empty values
	(*ppCreated)->lstChunkData		= 0; // right now, pointers must be assigned after calling this function
	(*ppCreated)->pExtendedData		= 0; // same with sizes
	(*ppCreated)->nExtendedDataSize	= 0;
};

void gvacquireRegionData( _GVOXEL_REGION_DATA* pRegionData )
{
if( 0 != pRegionData )
{
//#ifdef WIN32
//		InterlockedIncrement( &pRegionData->nRefCount ); // Still don't know if this works as I expect (perform atomic increase for thread-safety concerns)
//#else
	pRegionData->nRefCount++;
//#endif
}
}

// gvFreeRegionData
// this function crashes with NULL input
void gvfreeRegionData( _GVOXEL_REGION_DATA** ppRegionData )
{
if( 0 != (*ppRegionData) )
{
//#ifdef WIN32
//		if( 0 == InterlockedDecrement( &(*ppRegionData)->nRefCount ) ) 
//#else
	if( 0 == --((*ppRegionData)->nRefCount) )
//#endif
	{
		gvcleanVoxelRegionData( **ppRegionData );
		free( (*ppRegionData) );
	}
	(*ppRegionData)	= 0;
}
};
